lavaan形式のSEMモデルをsemパッケージ仕様のSEMモデルに変換して、semパッケージのpathDiagram関数でパス図を描く。

データ例

data(birthwt,package="MASS")
head(birthwt)
##    low age lwt race smoke ptl ht ui ftv  bwt
## 85   0  19 182    2     0   0  0  1   0 2523
## 86   0  33 155    3     0   0  0  0   3 2551
## 87   0  20 105    1     1   0  0  0   1 2557
## 88   0  21 108    1     1   0  0  1   2 2594
## 89   0  18 107    1     1   0  0  1   0 2600
## 91   0  21 124    3     0   0  0  0   0 2622

lavaanでSEM

library(lavaan)
library(semPlot)
model.l <- "
bwt ~ age + lwt + smoke
lwt ~ age
"
res.l <- lavaan(model.l, data=birthwt, auto.var = TRUE)
summary(res.l)
## lavaan (0.5-23.1097) converged normally after  60 iterations
## 
##   Number of observations                           189
## 
##   Estimator                                         ML
##   Minimum Function Test Statistic                0.257
##   Degrees of freedom                                 1
##   P-value (Chi-square)                           0.612
## 
## Parameter Estimates:
## 
##   Information                                 Expected
##   Standard Errors                             Standard
## 
## Regressions:
##                    Estimate    Std.Err   z-value  P(>|z|)
##   bwt ~                                                  
##     age                 7.154     9.822    0.728    0.466
##     lwt                 4.016     1.700    2.362    0.018
##     smoke            -269.257   104.604   -2.574    0.010
##   lwt ~                                                  
##     age                 1.039     0.413    2.517    0.012
## 
## Variances:
##                    Estimate    Std.Err   z-value  P(>|z|)
##    .bwt            491710.510 50581.719    9.721    0.000
##    .lwt               899.989    92.581    9.721    0.000
semPaths(res.l)

semの仕様に変換

tmp <- semPlotModel(res.l)
pars <- tmp@Pars
pars$label <- paste0("par",1:length(pars$par))
pars$edge[pars$edge == "~>"] <- "->"

tmp.m <- paste(paste(pars$lhs, pars$edge, pars$rhs), pars$label, pars$est, sep = ",", collapse = "\n")
model.s <- sem::specifyModel(textConnection(tmp.m))
model.s
##   Path            Parameter StartValue        
## 1 age -> bwt      par1      7.15384555654618  
## 2 lwt -> bwt      par2      4.01551504871354  
## 3 smoke -> bwt    par3      -269.256960704446 
## 4 age -> lwt      par4      1.03922628780356  
## 5 bwt <-> bwt     par5      491710.509577312  
## 6 lwt <-> lwt     par6      899.989484057973  
## 7 age <-> age     par7      27.9274376417234  
## 8 age <-> smoke   par8      -0.114386495338876
## 9 smoke <-> smoke par9      0.238235211780185

pathDiagramでパス図の作成

semパッケージのpathDiagram関数でパス図を作成しhtml形式で出力する。変数に代入したときの中身はDOT言語のコードになっている。

res.s <- sem::sem(model.s, data=birthwt)
g <- sem::pathDiagram(res.s,edge.labels="both")

画像ファイルでの保存

DOT言語をRで描くにはDiagrammeRgrViz関数を使う。その出力を、 htmlwidgetsパッケージのsaveWidget関数でhtml形式で保存して、 webshotパッケージのwebshot関数でウェブページのスクリーンショットでパス図を画像として保存する。

library(DiagrammeR)
library(htmlwidgets)
library(webshot)
saveWidget(grViz(g), file = "path.html")
webshot("path.html", file = "path.png")

不要なhtmlファイルはfile.remove関数で削除しておく。

file.remove("path.html")
## [1] TRUE